package com.sghd.fight.module.facade;

import com.sghd.common.event.EventBus;
import com.sghd.common.socket.core.ResultCallback;
import com.sghd.common.socket.session.Session;
import com.sghd.common.socket.session.SessionManager;
import com.sghd.common.utils.ManagedException;
import com.sghd.common.utils.codec.CryptUtils;
import com.sghd.fight.module.game.service.GameService;
import com.sghd.pojo.fight.game.ConnReq;
import com.sghd.pojo.fight.game.Result;
import com.sghd.pojo.fight.game.RoomType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author frank
 * @date 2018-10-29 10:13
 * @desc
 **/
@Component
public class GameFacadeImpl implements GameFacade {
    private static final Logger logger = LoggerFactory.getLogger(GameFacade.class);
    private final String CRYPT_KEY = "bbb";
    @Autowired
    private GameService gameService;
    @Autowired
    private EventBus eventBus;
    @Autowired
    private SessionManager sessionManager;

    @Override
    public void conn(Session session, ConnReq req, ResultCallback<Result<String>> callback) {
        long playerId = req.getPlayerId();
        try {
            int timestamp = req.getTimestamp();
            int now = (int) (System.currentTimeMillis() / 1000);
            /*System.out.println(timestamp);
            System.out.println(now);*/
            //配置秒超时
            if ((now - timestamp) > 60) {
                callback.call(Result.valueOf(-1, "登陆超时！"));
                return;
            }
            //TODO 签名验证
            boolean success = chkLoginKey(req.getPlayerId(), timestamp, req.getToken());
            if (success) {
                //token 验证成功
                Session prev = sessionManager.getSession(playerId);
                if (prev != null) {
                    //推送给客户端
                    logger.debug("玩家[{}]重复登陆！", req.getPlayerId());
                    sessionManager.kick(Session.KICK, playerId);//踢下线
                }
                sessionManager.bind(session, playerId);
                callback.call(Result.valueOf(0));
            } else {
                //签名失败，强制退出
                sessionManager.kick(Session.NORMAL, playerId);//踢除玩家下线
                throw new ManagedException(-1, "签名验证失败！");
            }
        } catch (ManagedException e) {
            logger.debug("初始化连接发生错误！{}", new Object[]{e});
            callback.call(Result.valueOf(e.getCode(), e.getMessage()));
        } catch (Exception e) {
            logger.error("初始化连接发生未知错误！", e);
            callback.call(Result.valueOf(-1, e.getMessage()));
        }
    }

    @Override
    public void match(Long playerId, RoomType type, int bigLevel, int level, ResultCallback<Result<Boolean>> callback) {
        try {
            gameService.match(playerId, bigLevel, level, type);//参加匹配
            callback.call(Result.valueOf(true));
        } catch (ManagedException e) {
            logger.debug("玩家[{}]参加匹配发生错误！{}", playerId, new Object[]{e});
            //TODO 弹窗
        } catch (Exception e) {
            logger.error("玩家[{}]参加匹配发生未知错误！", playerId, e);
        }
    }

    @Override
    public void cancelMatch(Long playerId) {
        try {
            gameService.cancelMatch(playerId);//取消匹配
        } catch (ManagedException e) {
            logger.debug("玩家[{}]取消匹配发生错误！{}", playerId, new Object[]{e});
            //TODO 弹窗
        } catch (Exception e) {
            logger.error("玩家[{}]取消匹配发生未知错误！", playerId, e);
        }
    }

    @Override
    public void ready(Long playerId, ResultCallback<Result<String>> callback) {
        try {
            gameService.ready(playerId, callback);//玩家准备
        } catch (ManagedException e) {
            logger.debug("玩家[{}]准备就绪发生错误！{}", playerId, new Object[]{e});
            //TODO 弹窗
        } catch (Exception e) {
            logger.error("玩家准备时未知错误！", playerId, e);
        }
    }

    @Override
    public void move(Long playerId, int first, int second, ResultCallback<Result<String>> callback) {
        try {
            gameService.move(playerId, first, second, callback);//进行交换
        } catch (ManagedException e) {
            logger.debug("玩家[{}]交换棋子[{}],[{}]发生错误！{}", playerId, first, second, new Object[]{e});
            callback.call(Result.valueOf(e.getCode(), e.getMessage()));
        } catch (Exception e) {
            logger.error("玩家[{}]交换未知错误！", playerId, e);
            callback.call(Result.valueOf(-1, e.getMessage()));
        }
    }

    @Override
    public void execute(Long playerId, int skillId, ResultCallback<Result<Object>> callback) {
        try {
            gameService.execute(playerId, skillId, callback);
        } catch (ManagedException e) {
            logger.debug("玩家[{}]执行技能[{}]发生错误！{}", playerId, skillId, new Object[]{e});
            callback.call(Result.valueOf(e.getCode(), e.getMessage()));
            //TODO 弹窗
        } catch (Exception e) {
            logger.error("玩家[{}]执行技能[{}]发生未知错误!", playerId, skillId, e);
            callback.call(Result.valueOf(-1, "执行技能发生未知错误!"));
        }
    }

    @Override
    public void test(Long playerId, ResultCallback<Object> callback) {
        try {
            gameService.test1(playerId, callback);
        } catch (ManagedException e) {
            //TODO 弹窗
        } catch (Exception e) {
            logger.error("玩家[{}]调用棋盘发生未知错误!", playerId, e);
        }
    }

    @Override
    public void time(Long playerId, ResultCallback<Object> callback) {
        try {
            Map<String, Object> body = new HashMap<>();
            body.put("time", System.currentTimeMillis());
            callback.call(body);
        } catch (ManagedException e) {
            //TODO 弹窗
        } catch (Exception e) {
            logger.error("玩家[{}]调用服务器时间[{}]发生未知错误!", e);
        }
    }

    @Override
    public void endTrustee(Long playerId, ResultCallback<Result<String>> callback) {
        try {
            gameService.endTrustee(playerId, callback);
        } catch (ManagedException e) {
            //TODO 弹窗
        } catch (Exception e) {
            logger.error("玩家[{}]执行托管[{}]发生未知错误!", e);
        }
    }

    @Override
    public void reconn(Long playerId, ResultCallback<Result<Object>> callback) {
        try {
            gameService.reconn(playerId, callback);
        } catch (ManagedException e) {
            logger.error("玩家[{}]重连发生未知错误!", playerId, e);
            callback.call(Result.valueOf(e.getCode(), e.getMessage()));
        } catch (Exception e) {
            logger.error("玩家[{}]重连发生未知错误!", playerId, e);
            callback.call(Result.valueOf(-1, "发生未知错误"));
        }
    }

    @Override
    public void resetSkill(Long playerId, Set<Integer> keeps) {
        try {
            gameService.resetSkill(playerId, keeps);
        } catch (ManagedException e) {
            logger.error("玩家[{}]重置技能发生未知错误!", playerId, e);
        } catch (Exception e) {
            logger.error("玩家[{}]重置技能发生未知错误!", playerId, e);
        }
    }

    @Override
    public void matchReady(Long playerId) {
        try {
            gameService.matchReday(playerId);
        } catch (ManagedException e) {
            logger.error("玩家[{}]确认进入游戏发生未知错误!", playerId, e);
        } catch (Exception e) {
            logger.error("玩家[{}]确认进入游戏发生未知错误!", playerId, e);
        }
    }

    /** 检查登录是否合法(true:合法,false:不合法) */
    private boolean chkLoginKey(long id, int timestamp, String token) {
        try {
            String md5 = CryptUtils.generateToken(CRYPT_KEY, id, timestamp);
            if (md5.equalsIgnoreCase(token)) {
                return true;
            }
        } catch (Exception e) {
            logger.debug("检查登录密匙时发生异常", e);
        }
        return false;
    }
}
